using System;
using System.Collections;
using System.Collections.Generic;
using System.Globalization;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Security.Permissions;
using System.Web;

namespace PickGold.Charting
{
	[AspNetHostingPermission(SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal), AspNetHostingPermission(SecurityAction.InheritanceDemand, Level = AspNetHostingPermissionLevel.Minimal)]
	public abstract class ChartNamedElementCollection<T> : ChartElementCollection<T>, INameController where T : ChartNamedElement
	{
		private List<T> _cachedState;
		private int _disableDeleteCount;

		internal event EventHandler<NameReferenceChangedEventArgs> NameReferenceChanged;

		internal event EventHandler<NameReferenceChangedEventArgs> NameReferenceChanging;

		internal ChartNamedElementCollection(IChartElement parent)
			: base(parent)
		{
		}

		public virtual T FindByName(string name)
		{
			foreach (T local in this)
			{
				if (local.Name == name)
				{
					return local;
				}
			}
			return default(T);
		}

		internal virtual void FixNameReferences(T item)
		{
		}

		public int IndexOf(string name)
		{
			int num = 0;
			foreach (T local in this)
			{
				if (local.Name == name)
				{
					return num;
				}
				num++;
			}
			return -1;
		}

		protected override void InsertItem(int index, T item)
		{
			if (string.IsNullOrEmpty(item.Name))
			{
				item.Name = this.NextUniqueName();
			}
			else if (!this.IsUniqueName(item.Name))
			{
				throw new ArgumentException(SR.ExceptionNameAlreadyExistsInCollection(item.Name, base.GetType().Name));
			}
			this.FixNameReferences(item);
			base.InsertItem(index, item);
			if ((base.Count == 1) && (item != null))
			{
				((INameController)this).OnNameReferenceChanged(new NameReferenceChangedEventArgs(null, item));
			}
		}

		internal bool IsNameReferenceValid(string name)
		{
			if (!string.IsNullOrEmpty(name) && !(name == "NotSet"))
			{
				return (this.IndexOf(name) >= 0);
			}
			return true;
		}

		public virtual bool IsUniqueName(string name)
		{
			return (this.FindByName(name) == null);
		}

		public virtual string NextUniqueName()
		{
			string name = string.Empty;
			string namePrefix = this.NamePrefix;
			for (int i = 1; i < 0x7fffffff; i++)
			{
				name = namePrefix + i.ToString(CultureInfo.InvariantCulture);
				if (this.IsUniqueName(name))
				{
					return name;
				}
			}
			return name;
		}

		protected override void RemoveItem(int index)
		{
			ChartNamedElement oldElement = (index < base.Count) ? ((ChartNamedElement)base[index]) : ((ChartNamedElement)default(T));
			if (this._disableDeleteCount == 0)
			{
				((INameController)this).OnNameReferenceChanged(new NameReferenceChangedEventArgs(oldElement, null));
			}
			base.RemoveItem(index);
			if (this._disableDeleteCount == 0)
			{
				ChartNamedElement newElement = (base.Count > 0) ? ((ChartNamedElement)base[0]) : ((ChartNamedElement)default(T));
				((INameController)this).OnNameReferenceChanged(new NameReferenceChangedEventArgs(oldElement, newElement));
			}
		}

		protected override void SetItem(int index, T item)
		{
			if (string.IsNullOrEmpty(item.Name))
			{
				item.Name = this.NextUniqueName();
			}
			else if (!this.IsUniqueName(item.Name) && (this.IndexOf(item.Name) != index))
			{
				throw new ArgumentException(SR.ExceptionNameAlreadyExistsInCollection(item.Name, base.GetType().Name));
			}
			this.FixNameReferences(item);
			ChartNamedElement oldElement = (index < base.Count) ? ((ChartNamedElement)base[index]) : ((ChartNamedElement)default(T));
			((INameController)this).OnNameReferenceChanging(new NameReferenceChangedEventArgs(oldElement, item));
			base.SetItem(index, item);
			((INameController)this).OnNameReferenceChanged(new NameReferenceChangedEventArgs(oldElement, item));
		}

		void INameController.DoSnapshot(bool save, EventHandler<NameReferenceChangedEventArgs> changingCallback, EventHandler<NameReferenceChangedEventArgs> changedCallback)
		{
			if (save)
			{
				this._cachedState = new List<T>(this);
				if (changingCallback != null)
				{
					this.NameReferenceChanging = (EventHandler<NameReferenceChangedEventArgs>)Delegate.Combine(this.NameReferenceChanging, changingCallback);
				}
				if (changedCallback != null)
				{
					this.NameReferenceChanged = (EventHandler<NameReferenceChangedEventArgs>)Delegate.Combine(this.NameReferenceChanged, changedCallback);
				}
			}
			else
			{
				if (changingCallback != null)
				{
					this.NameReferenceChanging = (EventHandler<NameReferenceChangedEventArgs>)Delegate.Remove(this.NameReferenceChanging, changingCallback);
				}
				if (changedCallback != null)
				{
					this.NameReferenceChanged = (EventHandler<NameReferenceChangedEventArgs>)Delegate.Remove(this.NameReferenceChanged, changedCallback);
				}
				this._cachedState.Clear();
				this._cachedState = null;
			}
		}

		bool INameController.IsUniqueName(string name)
		{
			return this.IsUniqueName(name);
		}

		void INameController.OnNameReferenceChanged(NameReferenceChangedEventArgs e)
		{
			if (!base.IsSuspended && (this.NameReferenceChanged != null))
			{
				this.NameReferenceChanged(this, e);
			}
		}

		void INameController.OnNameReferenceChanging(NameReferenceChangedEventArgs e)
		{
			if (!base.IsSuspended && (this.NameReferenceChanging != null))
			{
				this.NameReferenceChanging(this, e);
			}
		}

		internal void VerifyNameReference(string name)
		{
			if (((base.Chart != null) && !base.Chart.Serializing) && !this.IsNameReferenceValid(name))
			{
				throw new ArgumentException(SR.ExceptionNameNotFound(name, base.GetType().Name));
			}
		}

		public T this[string name]
		{
			get
			{
				int index = this.IndexOf(name);
				if (index == -1)
				{
					throw new ArgumentException(SR.ExceptionNameNotFound(name, base.GetType().Name));
				}
				return base[index];
			}
			set
			{
				int index = this.IndexOf(name);
				int num2 = base.IndexOf(value);
				bool flag = index > -1;
				bool flag2 = num2 > -1;
				if (!flag && !flag2)
				{
					base.Add(value);
				}
				else if (flag && !flag2)
				{
					base[index] = value;
				}
				else
				{
					if (!flag && flag2)
					{
						throw new ArgumentException(SR.ExceptionNameAlreadyExistsInCollection(name, base.GetType().Name));
					}
					if ((flag && flag2) && (index != num2))
					{
						throw new ArgumentException(SR.ExceptionNameAlreadyExistsInCollection(name, base.GetType().Name));
					}
				}
			}
		}

		protected virtual string NamePrefix
		{
			get
			{
				return typeof(T).Name;
			}
		}

		bool INameController.IsColectionEditing
		{
			get
			{
				return (this._disableDeleteCount == 0);
			}
			set
			{
				this._disableDeleteCount += value ? 1 : -1;
			}
		}

		IList INameController.Snapshot
		{
			get
			{
				return this._cachedState;
			}
		}
	}
}

